<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.7.1">
<title>Flowable迁移指导：Flowable V5到Flowable V6</title>
<style>

/* normalize.css */

button,hr,input{overflow:visible}audio,canvas,progress,video{display:inline-block}progress,sub,sup{vertical-align:baseline}html{font-family:sans-serif;line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0} menu,article,aside,details,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}a:active,a:hover{outline-width:0}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{}button,select{text-transform:none}[type=submit], [type=reset],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:ButtonText dotted 1px}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}[hidden],template{display:none}/*# sourceMappingURL=normalize.min.css.map */

/* tocbot 2.1.4 */

.toc{overflow-y:auto}.toc>ul{overflow:hidden;position:relative}.toc-list{margin:0;padding-left:10px}a.toc-link{color:currentColor;height:100%}.is-collapsible{max-height:1000px;overflow:hidden;transition:all 300ms ease-in-out}.is-collapsed{max-height:0}.is-position-fixed{position:fixed !important;top:0}.is-active-link{font-weight:700}.toc-link::before{background-color:#f9f9fb;content:' ';display:inline-block;height:inherit;left:8px;margin-top:-1px;position:absolute;width:2px}.is-active-link::before{background-color:#54BC4B}


/* Activiti Specific */

body {
  color: #494d55;
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

html, body {
  height: 100%;
  width: 100%;
  background: #f9f9f9;
  font-family: "Helvetica Neue",Helvetica,Roboto,Arial,sans-serif;
  color: #484848
}

.page-wrapper {
  min-height: 100%;
  /* equal to footer height */
  margin-bottom: -50px;
}

.page-wrapper:after {
  content: "";
  display: block;
  height: 50px;
}

#header {
  position:fixed;
  top:0px;
  z-index:100000;
  width:100%;
}

#header > h1 {
    background: #a0cc47;
    color: #f9f9f9;
    border-bottom: 2px solid #042944;
    padding: 20px 0 20px 20px;
    font-size: 40px;
    font-weight: 800;
    line-height: 1.1;
    margin: 0;
}

#header > h1:before {
  background:url('images/logo.png');
  background-size: 337px 54px; background-repeat: no-repeat;
  width: 337px;
  height: 54px;
  display:inline-block;
  content:'';
  margin-right: 30px;
}

#author {
  margin-left: 25%;
  font-size: 40px;
}

#content {
  margin: 129px 0 0 27%;
  padding: 10px 40px 0 20px;
  padding-right: 40px;
  line-height: 1.7;
  width: 65%;
  overflow-x: auto;
}

h2, h3, h4, h5, h6 {
  color: #00345a;
}

h2 {
  font-size: 26px;
  margin-top: 0;
  margin-bottom: 20px;
  font-weight: bold;
  padding-bottom: 10px;
  border-bottom: 1px solid #d7d7d7;
}

h3 {
  font-size: 18px;
  margin-top: 0;
  margin-bottom: 0;
  font-weight: bold;
  padding-bottom: 10px;
  /*border-bottom: 1px solid #d7d7d7;*/
}

h4 {
    font-size: 16px;
    font-weight: bold;
}

h5 {
    font-size: 14px;
    font-weight: bold;
}

h6, h7 {
    font-size: 14px;
    font-weight: bold;
    margin-top: 0;
    margin-bottom: 0;
}

.sect1, .sect2 {
  margin-bottom: 20px;
}

.clear
{
  clear: both;
}

.note, .listingblock, .literalblock{
  padding-left: 8px;
  padding-right: 8px;
  margin-bottom: 14px;
  background-color: #f7f7f9;
  border: 1px solid #e1e1e8;
  border-radius: 4px;
  color: #808080;
}

table.tableblock {
  width: 100%;
  max-width: 100%;
  margin-bottom: 20px;
  background-color: transparent;
  border-spacing: 0;
  border-collapse: collapse;
  border: 1px solid #ddd;
  table-layout: fixed;
}

table.tableblock>caption+thead>tr:first-child>td, table.tableblock>caption+thead>tr:first-child>th, table.tableblock>colgroup+thead>tr:first-child>td, table.tableblock>colgroup+thead>tr:first-child>th, table.tableblock>thead:first-child>tr:first-child>td, table.tableblock>thead:first-child>tr:first-child>th {
    border-top: 0;
}

table.tableblock > thead > tr > th {
    border-bottom-color: #8bd6d8;
}

table.tableblock>thead>tr>th {
    vertical-align: bottom;
    border-bottom: 1px solid #ddd;
}

table.tableblock>tbody>tr>td, table.tableblock>tbody>tr>th, table.tableblock>tfoot>tr>td, table.tableblock>tfoot>tr>th, table.tableblock>thead>tr>td, table.tableblock>thead>tr>th {
    padding: 8px;
    line-height: 1.42857143;
    vertical-align: top;
    border-top: 1px solid #ddd;
}

th {
    text-align: left;
}

table.tableblock > tbody > tr:nth-of-type(odd) {
    background-color: #f5f5f5;
}

table.tableblock > tbody > tr:nth-of-type(odd) {
    background-color: #f9f9f9;
}

td > p {
  margin:0;
}

td.content {
  white-space: normal;
}

pre, td, th {
   white-space: pre-wrap;
   white-space: -moz-pre-wrap;
   white-space: -pre-wrap;
   white-space: -o-pre-wrap;
   word-wrap: break-word;
}

img {
  max-width: 100%;
}

a {
  color: #007387;
}

a:hover {
  color: #004c59;
}

#toc-parent {
  width: 25%;
  float: left;
  height: 100%;
  overflow-y: auto;
  position: fixed;
  padding: 10px;
  border-right: 1px solid #ccc;
}

#generated-toc {
    width: 100%;
    height: 100%;
    font-size: 16px;
}

.toc-link {
  text-decoration: none;
}

.toc-list {
  margin: 0 20px 0 10px;
}

.toc-list-item {
  padding: 4px 0 4px 0;
}


div.sect5  p {
    margin-top: 0;
    margin-bottom: 0;
}

div.sect5  code {
    font-family: "Helvetica Neue",Helvetica,Roboto,Arial,sans-serif;
}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>
.listingblock .pygments .hll { background-color: #ffffcc }
.listingblock .pygments, .listingblock .pygments code { background: #f8f8f8; }
.listingblock .pygments .tok-c { color: #408080; font-style: italic } /* Comment */
.listingblock .pygments .tok-err { border: 1px solid #FF0000 } /* Error */
.listingblock .pygments .tok-k { color: #008000; font-weight: bold } /* Keyword */
.listingblock .pygments .tok-o { color: #666666 } /* Operator */
.listingblock .pygments .tok-ch { color: #408080; font-style: italic } /* Comment.Hashbang */
.listingblock .pygments .tok-cm { color: #408080; font-style: italic } /* Comment.Multiline */
.listingblock .pygments .tok-cp { color: #BC7A00 } /* Comment.Preproc */
.listingblock .pygments .tok-cpf { color: #408080; font-style: italic } /* Comment.PreprocFile */
.listingblock .pygments .tok-c1 { color: #408080; font-style: italic } /* Comment.Single */
.listingblock .pygments .tok-cs { color: #408080; font-style: italic } /* Comment.Special */
.listingblock .pygments .tok-gd { color: #A00000 } /* Generic.Deleted */
.listingblock .pygments .tok-ge { font-style: italic } /* Generic.Emph */
.listingblock .pygments .tok-gr { color: #FF0000 } /* Generic.Error */
.listingblock .pygments .tok-gh { color: #000080; font-weight: bold } /* Generic.Heading */
.listingblock .pygments .tok-gi { color: #00A000 } /* Generic.Inserted */
.listingblock .pygments .tok-go { color: #888888 } /* Generic.Output */
.listingblock .pygments .tok-gp { color: #000080; font-weight: bold } /* Generic.Prompt */
.listingblock .pygments .tok-gs { font-weight: bold } /* Generic.Strong */
.listingblock .pygments .tok-gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.listingblock .pygments .tok-gt { color: #0044DD } /* Generic.Traceback */
.listingblock .pygments .tok-kc { color: #008000; font-weight: bold } /* Keyword.Constant */
.listingblock .pygments .tok-kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
.listingblock .pygments .tok-kn { color: #008000; font-weight: bold } /* Keyword.Namespace */
.listingblock .pygments .tok-kp { color: #008000 } /* Keyword.Pseudo */
.listingblock .pygments .tok-kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
.listingblock .pygments .tok-kt { color: #B00040 } /* Keyword.Type */
.listingblock .pygments .tok-m { color: #666666 } /* Literal.Number */
.listingblock .pygments .tok-s { color: #BA2121 } /* Literal.String */
.listingblock .pygments .tok-na { color: #7D9029 } /* Name.Attribute */
.listingblock .pygments .tok-nb { color: #008000 } /* Name.Builtin */
.listingblock .pygments .tok-nc { color: #0000FF; font-weight: bold } /* Name.Class */
.listingblock .pygments .tok-no { color: #880000 } /* Name.Constant */
.listingblock .pygments .tok-nd { color: #AA22FF } /* Name.Decorator */
.listingblock .pygments .tok-ni { color: #999999; font-weight: bold } /* Name.Entity */
.listingblock .pygments .tok-ne { color: #D2413A; font-weight: bold } /* Name.Exception */
.listingblock .pygments .tok-nf { color: #0000FF } /* Name.Function */
.listingblock .pygments .tok-nl { color: #A0A000 } /* Name.Label */
.listingblock .pygments .tok-nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
.listingblock .pygments .tok-nt { color: #008000; font-weight: bold } /* Name.Tag */
.listingblock .pygments .tok-nv { color: #19177C } /* Name.Variable */
.listingblock .pygments .tok-ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
.listingblock .pygments .tok-w { color: #bbbbbb } /* Text.Whitespace */
.listingblock .pygments .tok-mb { color: #666666 } /* Literal.Number.Bin */
.listingblock .pygments .tok-mf { color: #666666 } /* Literal.Number.Float */
.listingblock .pygments .tok-mh { color: #666666 } /* Literal.Number.Hex */
.listingblock .pygments .tok-mi { color: #666666 } /* Literal.Number.Integer */
.listingblock .pygments .tok-mo { color: #666666 } /* Literal.Number.Oct */
.listingblock .pygments .tok-sa { color: #BA2121 } /* Literal.String.Affix */
.listingblock .pygments .tok-sb { color: #BA2121 } /* Literal.String.Backtick */
.listingblock .pygments .tok-sc { color: #BA2121 } /* Literal.String.Char */
.listingblock .pygments .tok-dl { color: #BA2121 } /* Literal.String.Delimiter */
.listingblock .pygments .tok-sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
.listingblock .pygments .tok-s2 { color: #BA2121 } /* Literal.String.Double */
.listingblock .pygments .tok-se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
.listingblock .pygments .tok-sh { color: #BA2121 } /* Literal.String.Heredoc */
.listingblock .pygments .tok-si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
.listingblock .pygments .tok-sx { color: #008000 } /* Literal.String.Other */
.listingblock .pygments .tok-sr { color: #BB6688 } /* Literal.String.Regex */
.listingblock .pygments .tok-s1 { color: #BA2121 } /* Literal.String.Single */
.listingblock .pygments .tok-ss { color: #19177C } /* Literal.String.Symbol */
.listingblock .pygments .tok-bp { color: #008000 } /* Name.Builtin.Pseudo */
.listingblock .pygments .tok-fm { color: #0000FF } /* Name.Function.Magic */
.listingblock .pygments .tok-vc { color: #19177C } /* Name.Variable.Class */
.listingblock .pygments .tok-vg { color: #19177C } /* Name.Variable.Global */
.listingblock .pygments .tok-vi { color: #19177C } /* Name.Variable.Instance */
.listingblock .pygments .tok-vm { color: #19177C } /* Name.Variable.Magic */
.listingblock .pygments .tok-il { color: #666666 } /* Literal.Number.Integer.Long */
</style>
</head>
<body class="book">
<div id="header">
<h1>Flowable迁移指导：Flowable V5到Flowable V6</h1>
</div>
<div id="content">
<div class="sect1">
<h2 id="_简介">1. 简介</h2>
<div class="sectionbody">
<div class="paragraph">
<p>本手册介绍了从Flowable V5.x迁移至Flowable V6时需要注意的事项。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_设计目标">2. 设计目标</h2>
<div class="sectionbody">
<div class="paragraph">
<p>V6版本的设计目标是：</p>
</div>
<div class="ulist">
<ul>
<li>
<p>完全向前兼容V5版本：数据库层面、概念层面以及代码层面。</p>
</li>
<li>
<p>重写核心引擎：直接执行BPMN 2.0（不再转换为中间模型）。</p>
</li>
<li>
<p>更简洁干净的运行时执行数据结构，重点关注结构的可预判性。</p>
</li>
<li>
<p>解耦持久层，以支持未来的不同实现。</p>
</li>
</ul>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_数据库迁移">3. 数据库迁移</h2>
<div class="sectionbody">
<div class="paragraph">
<p>从V5至V6不需要数据库迁移：V5与V6的数据库表结构基本一致，只是多了一些表与列。所有Flowable V5生成的数据都可以保留在数据库中，甚至包括活动的、执行中的流程实例。在V6引擎第一次运行时，会对表结构进行自动升级（同V5版本中一样）。除了一些小的数据库结构改动外，主要的改动是将作业表分拆为作业表、定时器作业表、暂停作业表与死信作业表。还未到期的定时器作业将移至新的定时器作业表；用尽重试次数的作业将移至死信作业表；已暂停流程实例的作业将移至暂停作业表。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_概念变化">4. 概念变化</h2>
<div class="sectionbody">
<div class="paragraph">
<p>称为Flowable V6的主要原因是完全重写了核心引擎。核心引擎执行的方式已经完全变化，将直接执行BPMN（在V5中使用的是中间模型）。同时，运行时执行的表现形式（<em>执行树</em>）也作了修改。总的来说，这些概念都大幅简化了，让执行更简单清晰，也让撰写自定义代码更容易更易懂。在V6中内嵌了一个V5引擎，在需要时可以保证完全的兼容性。</p>
</div>
<div class="paragraph">
<p>我们将在之后的文章中详细介绍引擎内部的工作。</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_破坏性改动">5. 破坏性改动</h2>
<div class="sectionbody">
<div class="paragraph">
<p>下列改动是破坏性改动（也就是说很可能导致编译错误）。</p>
</div>
<div class="sect2">
<h3 id="_包重命名org_activiti重命名为org_flowable">5.1. 包重命名：org.activiti重命名为org.flowable</h3>
<div class="paragraph">
<p>所有org.activiti包都已重命名为org.flowable。</p>
</div>
</div>
<div class="sect2">
<h3 id="_activiti类重命名">5.2. Activiti类重命名</h3>
<div class="paragraph">
<p>所有类名中包含的"Activiti"都已重命名，替换为Flowable。
例如，ActivitiEvent重命名为FlowableEvent，而ActivitiException重命名为FlowableException。</p>
</div>
</div>
<div class="sect2">
<h3 id="_activiti_cfg_xml重命名为flowable_cfg_xml">5.3. activiti.cfg.xml重命名为flowable.cfg.xml</h3>
<div class="paragraph">
<p>在Flowable引擎启动时读取的默认配置文件，已经从activiti.cfg.xml重命名为flowable.cfg.xml。
对于默认的Spring配置文件activiti-context.xml也是一样，已经重命名为flowable-context.xml.</p>
</div>
</div>
<div class="sect2">
<h3 id="_pvm类">5.4. PVM类</h3>
<div class="paragraph">
<p>以前在org.activiti.engine.impl.pvm包（及其子包）下的所有类都已移除。这是因为<em>PVM</em> (流程虚拟机 Process Virtual Machine)模型已被替换为一个更简单更轻量的模型。</p>
</div>
<div class="paragraph">
<p>这意味着<em>ActivitiImpl</em>、<em>ProcessDefinitionImpl</em>、<em>ExecutionImpl</em>及<em>TransitionImpl</em>都将失效。</p>
</div>
<div class="paragraph">
<p>在V5中这些类大多用于获取流程定义中包含的信息。在V6中，所有流程定义的信息都可以通过<em>BpmnModel</em>获取。这是一个BPMN 2.0 XML流程定义的Java表现形式（并对特定操作及搜索进行了增强）。</p>
</div>
<div class="paragraph">
<p>获取<em>BpmnModel</em>流程定义最快捷的方法是使用org.flowable.engine.RepositoryService服务：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>BpmnModel bpmnModel = repositoryService.getBpmnModel(myProcessDefinitionId);</pre>
</div>
</div>
<div class="paragraph">
<p>使用org.flowable.engine.impl.context.Context类获取<em>RepositoryService</em>，JavaDelegate或ActivityBehavior实现类：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>RepositoryService repositoryService = Context.getProcessEngineConfiguration().getRepositoryService();</pre>
</div>
</div>
<div class="paragraph">
<p>（请注意只有在上下文可用时才能如此操作，获取JavaDelegate和ActivityBehavior时也是这样）</p>
</div>
</div>
<div class="sect2">
<h3 id="_delegateexecution代替activityexecution">5.5. DelegateExecution代替ActivityExecution</h3>
<div class="paragraph">
<p>我们移除了ActivityExecution，并使用DelegateExecution类代替它。</p>
</div>
<div class="paragraph">
<p>所有ActivityExecution类中的方法都已复制到DelegateExecution类中。</p>
</div>
</div>
<div class="sect2">
<h3 id="_移除engineservices">5.6. 移除EngineServices</h3>
<div class="paragraph">
<p>移除了DelegateExecution中的getEngineServices方法，因为它已经没有实际作用，并导致在Flowable 6与内嵌的Flowable 5引擎中，DelegateExecution的使用不一致。</p>
</div>
<div class="paragraph">
<p>将所有对getEngineServices方法的调用，替换为对org.flowable.engine.impl.context.Context.getProcessEngineConfiguration方法的调用。</p>
</div>
</div>
<div class="sect2">
<h3 id="_作业定时器暂停与死信作业">5.7. 作业、定时器、暂停与死信作业</h3>
<div class="paragraph">
<p>Flowable V5中只有一个作业表，导致查询需要执行的作业时，查询条件异常复杂。</p>
</div>
<div class="paragraph">
<p>在Flowable V6中，作业被分拆成了作业表(ACT_RU_JOB)、定时器表(ACT_RU_TIMER_JOB)、暂停表(ACT_RU_SUSPENDED_JOB)与死信表(ACT_RU_DEADLETTER_JOB)。</p>
</div>
<div class="ulist">
<ul>
<li>
<p>作业表中的作业可以直接执行（类似异步作业与到期的定时器作业）。因此就不需要使用复杂的查询，唯一的where条件是lock time(锁定时间)不能为NULL。</p>
</li>
<li>
<p>定时器作业现在持久化在专门的定时器作业表中，并由一个线程检查到期需要执行的定时器作业。当定时器作业到期需要执行时，该作业会被移至作业表。</p>
</li>
<li>
<p>当作业执行器线程准备执行作业时，会从作业表获取并执行。</p>
</li>
<li>
<p>当流程定义或流程实例暂停时，其关联的作业将被移至单独的暂停作业表。这简化了作业执行器的查询，并清楚显示了暂停中的作业。</p>
</li>
<li>
<p>如果一个作业执行失败，它将被放入定时器作业表，并用 当前时间+引擎配置的作业失败等待时间 作为到期日期。在该作业到期将被执行时，会重新移至作业表，并被执行。如果重试次数减至0，则该作业将被移至死信表，不再自动执行。这样简化了默认的作业执行器查询，也清楚显示了卡住需要人工干预的作业。</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Flowable V6内嵌的Flowable V5引擎也能够使用这4个作业表。但是只会有一个线程池从数据库中获取作业，这个线程池在两个引擎间共享。当获取到一个作业后，会基于流程定义id检查引擎的版本，以判断作业由Flowable V6还是嵌入的Flowable V5引擎执行。</p>
</div>
</div>
<div class="sect2">
<h3 id="_向一个执行发信号">5.8. 向一个执行发信号</h3>
<div class="paragraph">
<p>在V5中，使用像是<em>runtimeService.signal(executionI);</em>这样的方法<em>向一个执行发信号</em>十分令人困惑。因为<em>信号(signal)</em>是一个BPMN 2.0概念和特性，它们的概念互相冲突。</p>
</div>
<div class="paragraph">
<p>在V6中，<em>signal()</em>方法更名为<em>trigger()</em>。</p>
</div>
<div class="paragraph">
<p>同时，用于实现可以被外部触发的行为的接口<em>SignalableActivityBehavior</em>，改名为<em>TriggerableActivityBehavior</em>。</p>
</div>
</div>
<div class="sect2">
<h3 id="_受检异常">5.9. 受检异常</h3>
<div class="paragraph">
<p>在V5中，<em>JavaDelegate</em>与<em>FlowableBehavior</em>之类的代理类在其签名中标示抛出<em>Exception</em>。像其他现代框架一样，在V6版本中已经不再使用受检异常。</p>
</div>
</div>
<div class="sect2">
<h3 id="_代理类">5.10. 代理类</h3>
<div class="paragraph">
<p><em>org.flowable.engine.impl.pvm.delegate.ActivityBehavior</em>的包变更为<em>org.flowable.engine.impl.delegate</em>。</p>
</div>
<div class="paragraph">
<p>从<em>DelegateExecution</em>中移除了下列方法：</p>
</div>
<div class="ulist">
<ul>
<li>
<p>end()</p>
</li>
<li>
<p>createdExecution()</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>而用ExecutionEntityManager的方法代替。可以通过Context.getCommandContext.getExecutionEntityManager()获取ExecutionEntityManager。</p>
</div>
</div>
<div class="sect2">
<h3 id="_实体管理器">5.11. 实体管理器</h3>
<div class="paragraph">
<p>在Flowable V5中，所有的实体管理器类（负责持久化，也包含一些逻辑）都没有接口。在V6中，所有的实体类都已经重命名为<em>Impl</em>后缀，并提供了不带后缀的接口。也就是说V5的实体管理器类名现在是相应的接口名。</p>
</div>
<div class="paragraph">
<p>所有的实体管理器接口都扩展了org.flowable.engine.impl.persistence.entity.EntityManager泛型接口。所有的实现类都实现了<em>AbstractEntityManager</em>泛型接口。</p>
</div>
<div class="paragraph">
<p>同时，为了保证一致性：</p>
</div>
<div class="ulist">
<ul>
<li>
<p>UserIdentityManager接口重命名为UserEntityManager</p>
</li>
<li>
<p>GroupIdentityManager接口重命名为GroupEntityManager</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_持久化对象重命名为实体">5.12. 持久化对象重命名为实体</h3>
<div class="paragraph">
<p><em>org.flowable.engine.impl.db.PersistentObject</em>类重命名为<em>Entity</em>，与其他类保持一致（实体管理器类等等）。</p>
</div>
<div class="paragraph">
<p>所有使用“持久化对象”的相关类也都已经重构为“实体”。</p>
</div>
</div>
<div class="sect2">
<h3 id="_身份逻辑与表的分离">5.13. 身份逻辑与表的分离</h3>
<div class="paragraph">
<p>在V5中，身份逻辑及表示流程引擎的必要部分。在V6中，这部分逻辑已经重构为独立的模块，名为<em>flowable-idm-engine</em>（其中IDM代表“身份管理(identity management)”）。相关的数据库表由这个引擎管理。为了保证兼容性，在启动流程引擎时，也会默认启用IDM引擎。可以在流程引擎配置中，将<em>disableIdmEngine</em>设置为<em>true</em>以禁用IDM引擎。如果禁用了IDM，就不会创建身份数据库表（以<em>ACT_ID</em>开头）。如果这些表已经存在，也可以删除。</p>
</div>
</div>
<div class="sect2">
<h3 id="_camel端点改名为flowable">5.14. Camel端点改名为flowable</h3>
<div class="paragraph">
<p>在使用Flowable Camel模块时，请确保使用flowable端点替代activiti端点。下面的Route作为简单的例子：</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="pygments highlight"><code data-lang="java"><table class="pyhltable"><tr><td class="linenos"><div class="linenodiv">1
2
3
4
5
6
7</div></td><td class="code"><span></span><span class="tok-kd">public</span> <span class="tok-kd">class</span> <span class="tok-nc">SimpleCamelCallRoute</span> <span class="tok-kd">extends</span> <span class="tok-n">RouteBuilder</span> <span class="tok-o">{</span>

  <span class="tok-nd">@Override</span>
  <span class="tok-kd">public</span> <span class="tok-kt">void</span> <span class="tok-nf">configure</span><span class="tok-o">()</span> <span class="tok-kd">throws</span> <span class="tok-n">Exception</span> <span class="tok-o">{</span>
    <span class="tok-n">from</span><span class="tok-o">(</span><span class="tok-s">&quot;flowable:SimpleCamelCallProcess:simpleCall&quot;</span><span class="tok-o">).</span><span class="tok-na">to</span><span class="tok-o">(</span><span class="tok-s">&quot;log:org.flowable.camel.examples.SimpleCamelCall&quot;</span><span class="tok-o">);</span>
  <span class="tok-o">}</span>
<span class="tok-o">}</span>
</td></tr></table></code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_v5兼容性">6. V5兼容性</h2>
<div class="sectionbody">
<div class="paragraph">
<p>在迁移至Flowable V6时（基本上就是替换classpath中的JAR包），所有当前的部署与流程定义都将<em>标记</em>为<em>V5版本</em>的工件。在很多地方（完成一个任务，启动一个新流程实例，指派任务等等）引擎都会检查相关的流程定义是否<em>标记为V5版本</em>。若是，则将其执行代理至<em>内嵌的微型V5引擎</em>。</p>
</div>
<div class="paragraph">
<p>也就是说为了简化迁移，可以选择逐步替换：首先在<em>V5模式</em>下运行当前的流程定义，直到已经验证并测试其行为与V6版本相同。</p>
</div>
<div class="paragraph">
<p>默认情况下，嵌入的V5引擎是<em>禁用的</em>！要启用它，在引擎配置中添加下列配置：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>&lt;property name="flowable5CompatibilityEnabled" value="true" /&gt;</pre>
</div>
</div>
<div class="paragraph">
<p><strong>并且</strong>在classpath中添加<strong>flowable5-compatibility</strong>（手动或通过Maven之类的依赖管理机制）。</p>
</div>
<div class="paragraph">
<p>如果默认的实现<em>org.flowable.compatibility.DefaultFlowable5CompatibilityHandler</em>不满足要求，也可以创建自定义的实现。可以将引擎配置中的<em>flowable5CompatibilityHandlerFactory</em>参数设置为所创建类的全限定类名。这个工厂类构造用于处理V5与V6桥接的类实例。</p>
</div>
<div class="paragraph">
<p>要让一个V5流程定义使用V6引擎运行，只需要重新部署它即可。新的流程实例将会在<em>V6模式</em>下运行，而之前的流程实例仍然在<em>V5模式</em>下运行。</p>
</div>
<div class="paragraph">
<p>如果出于某些原因，希望部署的新版流程定义仍然在<em>V5模式</em>下运行，可以使用下列代码：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>repositoryService.createDeployment()
      .addClasspathResource("xyz")
      .deploymentProperty(DeploymentProperties.DEPLOY_AS_FLOWABLE5_PROCESS_DEFINITION, Boolean.TRUE)
      .deploy();</pre>
</div>
</div>
<div class="paragraph">
<p>如果使用Flowable Spring模块，要使用Flowable V5兼容模式需要进行额外配置：</p>
</div>
<div class="listingblock">
<div class="content">
<pre>&lt;property name="flowable5CompatibilityEnabled" value="true" /&gt;
&lt;property name="flowable5CompatibilityHandlerFactory" ref="flowable5CompabilityFactory" /&gt;

....

&lt;bean id="flowable5CompabilityFactory" class="org.flowable.compatibility.spring.SpringFlowable5CompatibilityHandlerFactory" /&gt;</pre>
</div>
</div>
<div class="paragraph">
<p><strong>并且</strong>在classpath中添加<strong>flowable5-spring</strong>与<strong>flowable5-spring-compatibility</strong> JAR包（手动或通过Maven之类的依赖管理机制）。</p>
</div>
</div>
</div>
</div>
</body>
</html>